﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using XnaColor = Microsoft.Xna.Framework.Color;
using Skugo.Shared;

namespace Skugo
{
    public abstract class DebugDrawItem<T> where T : DebugDrawItem<T>
    {
        // Optional with defaults
        internal XnaColor ColorInternal = XnaColor.Red;
        internal Single DurationInternal;
        internal Int32 PriorityInternal;
        internal TransformSpace SpaceInternal = TransformSpace.WorldSpace;

        /// <summary>
        /// The color of the debug draw item.
        /// </summary>
        public T Color(XnaColor color)
        {
            this.ColorInternal = color;
            return this as T;
        }

        /// <summary>
        /// The amount of priority given to this draw. All draws with the same priority will
        /// be sorted and drawn in the same depth buffer. Different priorities will be drawn
        /// as different passes and will appear completely on top or below other objects.
        /// </summary>
        public T Priority(Int32 priority)
        {
            this.PriorityInternal = priority;
            return this as T;
        }

        /// <summary>
        /// The space that the debug draw is rendered in; either in world space, where it
        /// is transformed by a user-set world-to-projection matrix on the viewport, or
        /// in screen space where the coorindates are [-1, +1] on both the X and Y axes.
        /// </summary>
        public T Space(TransformSpace space)
        {
            this.SpaceInternal = space;
            return this as T;
        }

        /// <summary>
        /// The duration that we draw the item for. A duration
        /// of zero means that the item will only last one frame.
        /// </summary>
        public T Duration(Single timeSecondsOrZero)
        {
            // Make sure they didn't pass in what would be a persitant value
            if (timeSecondsOrZero < 0.0f)
            {
                throw new Exception("A negative duration is an invalid duration. Use zero for a single frame.");
            }

            this.DurationInternal = timeSecondsOrZero;
            return this as T;
        }
    }

    public class LineSegment : DebugDrawItem<LineSegment>
    {
        public LineSegment(Vector3 p1, Vector3 p2)
        {
            this.P1 = p1;
            this.P2 = p2;
        }

        // Required
        internal Vector3 P1;
        internal Vector3 P2;

        // Optional with defaults
        internal Single ArrowHead1Size;
        internal Single ArrowHead2Size;

        /// <summary>
        /// Set the size of the arrow head for the first point. A value of
        /// zero means that no arrow-head is drawn (this is the default).
        /// </summary>
        public LineSegment ArrowHead1(Single size)
        {
            this.ArrowHead1Size = size;
            return this;
        }

        /// <summary>
        /// Set the size of the arrow head for the first point. A value of
        /// zero means that no arrow-head is drawn (this is the default).
        /// </summary>
        public LineSegment ArrowHead2(Single size)
        {
            this.ArrowHead2Size = size;
            return this;
        }
    }
}
